//CSE 430 - Operating Systems
//Partha Dasgupta
//Spring '12
//Project 4

//Alan Tu
//Kelly Jesionowski

#include <stdio.h>
#include "sem.h"

/*
    Publisher and subscribers (pub-sub)
    
    This is similar to the producer-consumer problem.
    
    Publishers:
        - publish a sequence of items
        - only 1 publisher
        
    Subscribers:
        - each subscriber gets to read every item published
        - number not known in advance (5 max)
        - new subscribers may be created during run (dynamic)
        - new subscriber can read any one of the items already
            in the queue of unread items or the first new item
            to be published/added to queue
        - do not terminate
        
    
    Boundary conditions must be met:
        - slow subscribers block the publisher and vice versa
        
    Instructions:
        - Do not use multiple (5) queues as suggested by midterm problem.
            There should be only 1 queue implemented using a circular array
            just like the producer-consumer program discussed in class or
            assigned in Project 3.
        
        - Items can be integers. All items published are to be read by ALL subscribers
            Ater a few items the subscriber starts another subscriber. Do this until 5
            subscribers have been created and no further ones are created.
            
        - 
*/

#define BUFF_SIZE 4

semaphore_t *full;
semaphore_t *empty;
semaphore_t *mutex;
int buffer[BUFF_SIZE];
int producers, consumers, in, out;

void printBuff(){
	int i, n;
	printf("Buffer: ");
	for(i = 0; i < BUFF_SIZE; i++){
		if(buffer[i] != 0){
			printf("%d ", buffer[i]);
		}
	}
	printf("\n\n");
}

void producer(){
	producers++;
	int prod_num = producers;

	int item;
	while(1){
		item = rand() % 100;
		P(&full);
		P(&mutex);
		printf("Producer %d: %d\n", prod_num, item);
		buffer[in] = item;
		printBuff();
		yield();
		in = (in+1) % BUFF_SIZE;
		V(&mutex);
		V(&empty);
		/*if((item % 7) == 0){
			start_thread(producer);
		}*/
	}
}

void consumer(){
	consumers++;
	int cons_num = consumers;	

	int item;
	while(1){
		P(&empty);
		P(&mutex);
		item = buffer[out];
		printf("Consumer %d: %d\n\n", cons_num, item);
		buffer[out] = 0;
		out = (out+1) % BUFF_SIZE;
		V(&mutex);
		V(&full);
		/*if((item % 3) == 0){
			start_thread(consumer);
		}*/
	}
}

void main(){
	initSem(&full, BUFF_SIZE);
	initSem(&empty, 0);
	initSem(&mutex, 1);
    InitQueue(&readyQ);
    
	start_thread(producer);
	start_thread(producer);
	start_thread(consumer);
	start_thread(consumer);
	start_thread(consumer);
	start_thread(consumer);
    
    run();
}
